package com.lk.user.service.impl;

//import com.lk.basic.config.RegisterNoticeRabbitmqConfig;
import com.alibaba.fastjson.JSONObject;
import com.lk.basic.util.AjaxResult;
import com.lk.basic.util.HttpClientUtils;
import com.lk.basic.util.MD5Utils;
import com.lk.basic.util.WxConstants;
import com.lk.user.domain.Logininfo;
import com.lk.user.domain.User;
import com.lk.user.domain.Wxuser;
import com.lk.user.dto.AccountRegisterDTO;
import com.lk.user.dto.NodiceContentDTO;
import com.lk.user.dto.UserBindWechatDTO;
import com.lk.user.mapper.LogininfoMapper;
import com.lk.user.mapper.UserMapper;
import com.lk.user.mapper.WxuserMapper;
import com.lk.user.service.IUserService;
import com.lk.basic.service.impl.BaseServiceImpl;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lk
 * @since 2022-11-15
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {

    @Autowired
    private LogininfoMapper logininfoMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private WxuserMapper wxuserMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Override
    @Transactional
    public void accountRegister(AccountRegisterDTO dto) {
        String mobile = dto.getMobile();
        String username = dto.getUsername();
        String confirmPassword = dto.getConfirmPassword();
        String password = dto.getPassword();
        String smsCode = dto.getSmsCode();

        //参数非空
        if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(username)
                ||StringUtils.isEmpty(password)||StringUtils.isEmpty(confirmPassword)||StringUtils.isEmpty(smsCode)){
            throw new RuntimeException("参数有错误，请核实");
            //AjaxResult.me().setSuccess(false).setResult("参数有错误，请核实");
        }
        //密码验证
        if (!confirmPassword.equals(password)){
            throw new RuntimeException("两次密码输入不一致，请检查");
        }
        //校验手机验证码是否过期
        String smsCodeStr=(String)redisTemplate.opsForValue().get("rediser_sms_code_"+mobile);
        if (StringUtils.isEmpty(smsCodeStr)){
            throw new RuntimeException("手机验证码已过期");
        }
        //校验手机验证码是否正确
        smsCodeStr=smsCodeStr.split(":")[0];
        if (!smsCode.equals(smsCodeStr)){
            throw new RuntimeException("验证码输入错误，请核实");
        }
        //判断用户名是否存在
        Logininfo logininfo=logininfoMapper.findUserByUsername(username);
        if (Objects.nonNull(logininfo)){
            throw new RuntimeException("用户名已存在，请更改");
        }
        //将数据填入logininfo表
        logininfo=new Logininfo();
        logininfo.setUsername(username);
        String salt= UUID.randomUUID().toString();
        logininfo.setSalt(salt);
        password= MD5Utils.encrypByMd5("123"+salt+"123"+password);
        logininfo.setPassword(password);
        logininfo.setType(1);
        logininfo.setDisable(1);
        logininfo.setPhone(mobile);
        logininfoMapper.insert(logininfo);

        User user=new User();
        user.setUsername(username);
        user.setSalt(salt);
        user.setPassword(password);
        user.setState(2);
        user.setCreatetime(new Date());
        user.setLogininfoId(logininfo.getId());
        userMapper.insert(user);

        //短信邮件通知注册成功
    /*    rabbitTemplate.convertAndSend(RegisterNoticeRabbitmqConfig.EXCHANGE_TOPICS_INFORM,
                "inform.sms",new NodiceContentDTO(mobile,"短信通知，注册成功"));
        rabbitTemplate.convertAndSend(RegisterNoticeRabbitmqConfig.EXCHANGE_TOPICS_INFORM,
                "inform.email",new NodiceContentDTO(mobile,"邮件通知，注册成功"));*/

    }

    @Override
    public AjaxResult userBindWechat(UserBindWechatDTO dto) {
        String mobile = dto.getMobile();
        String verifyCode = dto.getVerifyCode();
        String accessToken = dto.getAccessToken();
        String openid = dto.getOpenid();
        // 1 参数非空校验
        if(StringUtils.isEmpty(mobile) || StringUtils.isEmpty(verifyCode) || StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openid)){
            return AjaxResult.me().setSuccess(false).setMessage("参数异常!请检查后重新提交!");
        }

        // 2 校验手机验证码是否正确
        String smsCodeFromRedis = (String)redisTemplate.opsForValue().get("binder_sms_code_"+mobile);
        if(StringUtils.isEmpty(smsCodeFromRedis)){
            return AjaxResult.me().setSuccess(false).setMessage("手机验证码已过期,请重新获取!");
        }
        smsCodeFromRedis = smsCodeFromRedis.split(":")[0];
        if(!verifyCode.equalsIgnoreCase(smsCodeFromRedis)){
            return AjaxResult.me().setSuccess(false).setMessage("验证码输入错误!");
        }

        // 3 根据手机号判断用户是否已注册
        User user = userMapper.loadByPhone(mobile);
        Logininfo logininfo = null;
        if(Objects.nonNull(user)){
            // 3.1 如果用户已注册,判断用户是否已绑定微信用户
            Wxuser wxuser = wxuserMapper.loadByUserId(user.getId());
            if(Objects.nonNull(wxuser)){
                // 3.1.1 如果已绑定,就直接抛异常,提示用户 请先解绑
                return AjaxResult.me().setSuccess(false).setMessage("该手机号已绑定微信用户,请解绑后再操作!");
            }else{
                // 3.1.2 如果未绑定,就将用户与微信用户绑定,免密登录
                // 获取wxUser对象
                wxuser = buildWxuser(accessToken, openid);
                wxuser.setUserId(user.getId());
                // 3.1.2.3 保存wxUser到数据库
                wxuserMapper.insert(wxuser);
                // 3.1.2.4 获取当前用户的logininfo登陆信息,用来做免密登陆
                logininfo = logininfoMapper.loadByUserId(user.getId());
            }
        }else{
            // 3.2 如果用户未注册,直接添加登录信息 用户信息 微信用户信息,免密登录
            // 3.2.1 封装logininfo对象
            logininfo = buildLogininfo(mobile);
            logininfoMapper.insert(logininfo);
            // 3.2.2 封装并保存user对象
            user = logininfo2User(logininfo);
            userMapper.insert(user);
            // 3.2.3 获取微信用户对象,并保存
            Wxuser wxuser = buildWxuser(accessToken, openid);
            wxuser.setUserId(user.getId());
            wxuserMapper.insert(wxuser);
        }
        // 4 免密登录
        String token = UUID.randomUUID().toString();
        redisTemplate.opsForValue().set(token, logininfo,30, TimeUnit.MINUTES);

        // 5 将token和登录信息都返回给前端
        Map<String,Object> result = new HashMap<>();
        result.put("token", token);
        logininfo.setPassword("");
        logininfo.setSalt("");
        result.put("loginInfo", logininfo);
        return AjaxResult.me().setResult(result);
    }

    private Logininfo buildLogininfo(String mobile) {
        Logininfo logininfo = new Logininfo();
        logininfo.setUsername(UUID.randomUUID().toString());    // 默认生成的用户名
        logininfo.setPhone(mobile);
        String salt = UUID.randomUUID().toString();
        logininfo.setSalt(salt);
        String password = MD5Utils.encrypByMd5("123"+salt+"789"+"123456");
        logininfo.setPassword(password);
        logininfo.setType(1);
        logininfo.setDisable(1);
        return logininfo;
    }

    private Wxuser buildWxuser(String accessToken, String openid) {
        // 3.1.2.1 先通过accessToken openid获取微信用户
        String getUserUrl = WxConstants.GET_USER_URL
                .replace("ACCESS_TOKEN", accessToken)
                .replace("OPENID", openid);
        String wxUserStr = HttpClientUtils.httpGet(getUserUrl);
        // 3.1.2.2 将获得的微信用户转换为WxUser对象,并为wxUser中的user_id赋值
        Wxuser wxuser = wxUserStr2Obj(wxUserStr);
        return wxuser;
    }

    private User logininfo2User(Logininfo logininfo) {
        User user = new User();
        BeanUtils.copyProperties(logininfo, user);
        // 单独设置字段
        user.setState(2);
        user.setCreatetime(new Date());
        user.setLogininfoId(logininfo.getId());
        return user;
    }
    private Wxuser wxUserStr2Obj(String wxUserStr) {
        //Wxuser wxuser = JSONObject.parseObject(wxUserStr, Wxuser.class);
        JSONObject jsonObject = JSONObject.parseObject(wxUserStr);
        if(StringUtils.isEmpty(jsonObject.getString("openid"))){
            throw new RuntimeException("当前微信用户已过期!请重新扫码登录!");
        }
        Wxuser wxuser = new Wxuser();
        wxuser.setOpenid(jsonObject.getString("openid"));
        wxuser.setNickname(jsonObject.getString("nickname"));
        wxuser.setSex(jsonObject.getInteger("sex"));
        wxuser.setUnionid(jsonObject.getString("unionid"));
        wxuser.setHeadimgurl(jsonObject.getString("headimgurl"));
        String country = jsonObject.getString("country");
        String province = jsonObject.getString("province");
        String city = jsonObject.getString("city");
        wxuser.setAddress(country+province+city);
        return wxuser;
    }


}
